﻿//--------------------------------------------------------------------------
// 
//  Copyright (c) Chili Software.  All rights reserved. 
// 
//  File: IUserDefinedType.cs
//
//  Description: Interface for user-defined types.
// 
//--------------------------------------------------------------------------

using System;

namespace Chili.Opf3
{
	/// <summary>
	/// Interface implemented by user-defined types (types that are not directly supported by the storage). 
	/// </summary>
	/// <remarks>
	/// <para><b>Attention:</b> Classes implementing this interface need a constructor without arguments. It may be either 
	/// public, internal or private.</para>
	/// <para>
	/// This interface allows creating user-defined types (types that are nod directly supported by the storage) 
	/// that can then be persisted to the storage and loaded from the storage. If the storage does not 
	/// directly implement the type you want save you can implement this interface to save that object 
	/// to the storage.
	/// </para>
	/// <para>
	/// The interface contains two methods:<br />
	/// <see cref="Opf3.IUserDefinedType.FromSimpleDataType(object)">FromSimpleType</see> and 
	/// <see cref="Opf3.IUserDefinedType.ToSimpleDataType">ToSimpleDataType.</see> The first method
	/// has one argument that is set during load and allows you to populate the object with the data from the
	/// storage. The second method converts the object to a type that can be saved to the storage (for 
	/// example a xml string) and is called during the save process.
	/// Currently <see cref="Opf3.ID{T}">ID</see>, <see cref="Opf3.Blob">Blob</see> and
	/// the <see cref="Opf3.DynamicProperties">DynamicProperties</see> implement this interface.
	/// </para>
	/// </remarks>
	/// <example>
	/// The following example shows how to implement the interface in your own types.
	///		<code lang="CS">
	/// public class FirstNameLastNamePair : IUserDefinedType
	/// {
	///		private string _firstName;
	///		private string _lastName;
	/// 
	///		public void FromSimpleDataType(object value)
	///		{
	///			if (!(value is string))
	///				throw new NotSupportedException("Value must be a string.");
	///				
	///			string[] tokens = ((string)value).Split(' ');
	///			if (tokens.Length != 2)
	///				throw new NotSupportedException("Only firstname-lastname pair is supported.");
	///			
	///			_firstName = tokens[0];
	///			_lastName = tokens[1];
	///		}
	/// 
	///		public object ToSimpleDataType()
	///		{
	///			return _firstName + " " + _lastName;
	///		}
	/// 
	///		public Type SupportedType
	///		{
	///			get { return typeof(string); }
	///		}
	/// 
	///		// ... Other properties and methods.
	/// }
	///		</code>
	/// </example>
	public interface IUserDefinedType : ICloneable
	{
		/// <summary>
		/// Populates the type that implements the interface (a type that can't be directly saved or 
		/// loaded from the storage) with data from the storage.
		/// </summary>
		/// <param name="value">The simple type representation in the storage (for example an xml string).</param>
		void FromSimpleDataType(object value);

		/// <summary>
		/// Converts the user-defined type to a type that can be persisted to the storage. You could
		/// return here, for example, an xml string or something else that can be saved to the storage.
		/// </summary>
		/// <returns>
		/// The IUserDefinedType converted to a simple type that is saved to the
		/// storage.
		/// </returns>
		object ToSimpleDataType();

		/// <summary>
		/// Returns the type supported by the class implementing this interface. The supported type is the type
		/// of the value that is returned when converting to a simple type (the type supported by the storage).
		/// </summary>
		Type SupportedType { get; }
	}
}
